package com.stox.ui.javafx.core.widget;

import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.stox.dto.intf.Application;
import com.stox.ui.javafx.core.event.handler.StageResizeRelocateMouseEventHandler;
import com.stox.ui.javafx.core.widget.wrapper.ImageView;

@Component
public class StoxStage extends Stage implements InitializingBean, BeanPostProcessor{
	
	//Need global access to stage to avoid circular dependency in spring
	private static StoxStage  instance;
	
	public static StoxStage getInstance(){
		return instance;
	}
	
	private ApplicationContext applicationContext;
	
	private TitleBar titleBar;
	
	private BorderPane root = new BorderPane();
	
	private StackPane contentPane = new StackPane();
	
	private StageResizeRelocateMouseEventHandler stageResizeRelocateMouseEventHandler;
	
	private EventHandler<DragEvent> onDragOverEventHandler = new EventHandler<DragEvent>() {
		@Override
		public void handle(DragEvent event) {
			  if (event.getDragboard().hasString()) {
                  event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
              }
			  event.consume();
		}
	};
	
	private EventHandler<DragEvent> onDragDroppedEventHandler = new EventHandler<DragEvent>(){
		@Override
		public void handle(DragEvent event) {
			try {
				((Application)applicationContext.getBean(Class.forName(event.getDragboard().getString()))).launch(applicationContext);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			event.setDropCompleted(true);
			event.consume();
		}
	};
	
	public StoxStage() {
		super();
		setTitle("Stox");
		getIcons().add(new ImageView("icon-title.png").getImage());
		StoxStage.instance = this;
		initStyle(StageStyle.UNDECORATED);
		setScreenBounds();
		setMinHeight(100);
		setMinWidth(300);
		root.setCenter(contentPane);
		setScene(createScene());
	}
	
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}
	
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}

	private Scene createScene(){
		Scene scene  = new Scene(root, getWidth(),getHeight(), Color.BLACK);
		scene.getStylesheets().add(getClass().getClassLoader().getResource("style/default-black-skin.css").toExternalForm());
		scene.setOnDragOver(onDragOverEventHandler);
		scene.setOnDragDropped(onDragDroppedEventHandler);
		return scene;
	}

	private void setScreenBounds(){
		Rectangle2D rectangle = Screen.getPrimary().getVisualBounds();
		setX(rectangle.getMinX());
		setY(rectangle.getMinY());
		setHeight(rectangle.getHeight());
		setWidth(rectangle.getWidth());
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		stageResizeRelocateMouseEventHandler.applyStageResizeRelocateMouseEventHandler(this);
	}
	
	@Autowired
	public void setStageResizeRelocateMouseEventHandler(StageResizeRelocateMouseEventHandler stageResizeRelocateMouseEventHandler){
		this.stageResizeRelocateMouseEventHandler = stageResizeRelocateMouseEventHandler;
	}
	
	@Autowired
	public void setApplicationContext(ApplicationContext applicationContext){
		this.applicationContext = applicationContext;
	}
	
	@Autowired
	public void setTitleBar(TitleBar titleBar){
		this.titleBar = titleBar;
		root.setTop(titleBar);
	}
	
	public TitleBar getTitleBar(){
		return titleBar;
	}
	
	private boolean maximized = false;
	private Rectangle2D backupWindowBounds = null;
	
	public void toogleMaximized() {
		double x = getX() < 0 ? 0 : getX();
		double y = getY() < 0 ? 0 : getY();
		Screen screen = (Screen)Screen.getScreensForRectangle(x, y, 1d, 1d).get(0);
		
		if (this.maximized) {
			this.maximized = false;
			if (this.backupWindowBounds != null) {
				setX(this.backupWindowBounds.getMinX());
				setY(this.backupWindowBounds.getMinY());
				setWidth(this.backupWindowBounds.getWidth());
				setHeight(this.backupWindowBounds.getHeight());
			}
		} else {
			this.maximized = true;
			this.backupWindowBounds = new Rectangle2D(getX(),getY(),getWidth(),getHeight());
			setX(screen.getVisualBounds().getMinX());
			setY(screen.getVisualBounds().getMinY());
			setWidth(screen.getVisualBounds().getWidth());
			setHeight(screen.getVisualBounds().getHeight());
		}
	}
	
	public BorderPane getRootPane() {
		return root;
	}
	
	public StackPane getContentPane() {
		return contentPane;
	}
	
}
